﻿Imports System.Globalization

Partial Public Class Form1
    'Dim level As Integer = 0
    Dim LastRow As Integer = 0
    Dim cursorStack As New Stack(Of Cursor)

    Private Function GetDirectoryInfo(DriveName As String, ParentPath As String, directoryInf As System.IO.DirectoryInfo, RowTagIn As String, ByRef ThisDirIndex As Integer, parentIndex As Integer, parentLevel As Integer) As DirDetails
        'Application.DoEvents()
        'If DoCancel Then
        'Return Nothing
        'End If
        'Dim cursor As Boolean = DataGridView1.UseWaitCursor
        cursorStack.Push(Cursor.Current)
        Cursor.Current = Cursors.WaitCursor
        Dim level As Integer = parentLevel + 1
        Dim RowTag As String = RowTagIn + "," + level.ToString("D3") + "." + ThisDirIndex.ToString("D3")


        Dim details As New DirDetails

        Dim dirName As String
        dirName = directoryInf.Name

        Dim Files() As System.IO.FileInfo = Nothing
        Dim Dirs() As System.IO.DirectoryInfo = Nothing
        Dim FileCount As Integer
        Dim DirsCount As Integer

        Dim LocalChildCount As Integer
        Dim ChildCount As Integer = 0
        Dim Subindex As Integer = 0
        Dim currentRow As DataGridViewRow
        currentRow = Nothing
        Dim accessDenied As Boolean = False

        ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
        'For certain system directories that will generate access etc. denied don't interogate
        details.RowTag = RowTag
        Dim di() As Boolean
        ReDim di(14)
        di(0) = directoryInf.Attributes.HasFlag(IO.FileAttributes.Archive)
        di(1) = directoryInf.Attributes.HasFlag(IO.FileAttributes.Compressed)
        di(2) = directoryInf.Attributes.HasFlag(IO.FileAttributes.Directory)
        di(3) = directoryInf.Attributes.HasFlag(IO.FileAttributes.Encrypted)
        di(4) = directoryInf.Attributes.HasFlag(IO.FileAttributes.ReadOnly)
        di(5) = directoryInf.Attributes.HasFlag(IO.FileAttributes.Device)
        di(6) = directoryInf.Attributes.HasFlag(IO.FileAttributes.Hidden)
        di(7) = directoryInf.Attributes.HasFlag(IO.FileAttributes.Normal)
        di(8) = directoryInf.Attributes.HasFlag(IO.FileAttributes.NotContentIndexed)
        di(9) = directoryInf.Attributes.HasFlag(IO.FileAttributes.Offline)
        di(10) = directoryInf.Attributes.HasFlag(IO.FileAttributes.ReparsePoint)
        di(11) = directoryInf.Attributes.HasFlag(IO.FileAttributes.SparseFile)
        di(12) = directoryInf.Attributes.HasFlag(IO.FileAttributes.System)
        di(13) = directoryInf.Attributes.HasFlag(IO.FileAttributes.Temporary)
        accessDenied = (di(2) And di(6) And di(12)) Or (di(2) And di(4) And di(6) And di(8))

        Try



            If (level <= (MaxDepth.Value)) Then
                Dim dd As String() = New String() {"", level.ToString(), directoryInf.FullName, ParentPath, RowAccessStates.OK.ToString(), RowDataStates.Uninitiated.ToString(), "", "", "", "", "", DriveName, dirName, parentIndex.ToString(), ThisDirIndex.ToString(), details.RowTag, "0", "0", "0", "0", "0", "0"}
                LastRow = DataGridView1.Rows.Add(dd)
                currentRow = DataGridView1.Rows(LastRow)

                currentRow.DefaultCellStyle.ForeColor = ColorForeUninitiated
                currentRow.DefaultCellStyle.BackColor = ColorBackUninitiated


                Dim nav As String = "|"
                For i = 1 To level
                    nav = "  " + nav
                Next
                currentRow.Cells("Nav").Value = nav
                If (level > (CurrentlevelfromUI + MaxShowDepth.Value)) Then
                    currentRow.Visible = False
                Else
                    currentRow.Visible = True
                    DataGridView1.Refresh()
                End If
            End If

        Catch ex As Exception
            MessageBox.Show("Error: Loc 4.1 Level " + level.ToString() + " Directory " + Name, "FileSystemExplorer", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try


        If accessDenied Then
            If (Not currentRow Is Nothing) Then
                currentRow.Cells("RowState").Value = RowDataStates.Hidden
                If (level > (CurrentlevelfromUI + MaxShowDepth.Value)) Then
                    currentRow.Visible = False
                Else
                    currentRow.Visible = True
                    DataGridView1.Refresh()
                End If
                currentRow.Cells("RowAccessState").Value = RowAccessStates.AccessDenied
                If (level <> 0) Then
                    currentRow.DefaultCellStyle.ForeColor = SubLevelActiveForeColor(level - 1)
                    currentRow.DefaultCellStyle.BackColor = SubLevelActiveBackColor(level - 1)
                Else
                    currentRow.DefaultCellStyle.ForeColor = DriveInActiveForeColor
                    currentRow.DefaultCellStyle.BackColor = DriveInActiveBackColor
                End If
            End If
            level -= 1
            Cursor.Current = cursorStack.Pop()
            Return details
        End If

        'Get further details of directory
        Try

            'Get all all files that fit the filename mask
            Dim filenameMask As String = txtFilenameMask.Text + ".*"
            If filenameMask = ".*" Then filenameMask = "*.*"
            Files = directoryInf.GetFiles(filenameMask)

            If (Files.Count <> 0) And (Trim(txtFileTypes.Text) <> "") Then
                'Apply the file type filter

                Dim sep() As Char = ",".ToCharArray()
                Dim filetypesStr() As String = Trim(txtFileTypes.Text).Split(sep)

                'This Linq line replaces the next commented out loop. Remove any leading  , as optional and tyhen add to all
                Dim filetypes = From xn As String In filetypesStr Where Trim(xn.Replace(".", "")) <> "" Select "." + Trim(xn.Replace(".", ""))

                'Convert the comma separate list of extensions to a List of
                'Dim filetypes As List(Of String) = New List(Of String)
                'For Each filetyp As String In filetypesStr
                '    They may have leading and trailing spaces so remove; and remove any leading .
                '    filetyp = filetyp.Replace(".", "")
                '    filetyp = "." + Trim(filetyp)
                '    Remove any blanks as well
                '    If (filetyp <> "") Then
                '        filetypes.Add(filetyp)
                '    End If
                'Next

                'Now get those file types
                If (filetypes.Count <> 0) Then
                    Try
                        Dim var = From fi As System.IO.FileInfo In Files Select fi Where filetypes.Contains(fi.Extension)
                        Files = var.ToArray()
                    Catch ex As Exception
                        MessageBox.Show("Error: Loc 4.2 Level " + level.ToString() + " Directory " + Name, "FileSystemExplorer", MessageBoxButtons.OK, MessageBoxIcon.Error)
                    End Try
                End If
            End If

            'Default Directory mask to *
            Dim DirsMask As String = txtDirsMask.Text
            'If mask is blank then make *
            If (DirsMask = "") Then DirsMask = "*"
            'If Mask doesn't any have wildstars or double quotes then append then  * That way 
            If Not (DirsMask.Contains("*") Or DirsMask.Contains("?") Or DirsMask.Contains("""")) Then DirsMask += "*"
            'If Mask has " then remove them now. That way can just search for a specific dir but must be in double  quotes
            If DirsMask.Contains("""") Then DirsMask = DirsMask.Replace("""", "")

            Dirs = directoryInf.GetDirectories(DirsMask, IO.SearchOption.TopDirectoryOnly)

            FileCount = Files.Count
            DirsCount = Dirs.Count
            details.FileCount += FileCount
            details.DirsCount += DirsCount
            If (Not currentRow Is Nothing) Then
                currentRow.Cells("FileCount").Value = FileCount.ToString()
                currentRow.Cells("DirectoryCount").Value = DirsCount.ToString()
            End If
        Catch ex As Exception
            accessDenied = True
            If (Not currentRow Is Nothing) Then
                'AuthAccessCheckBox = CType(currentRow.Cells("AuthAccess"), DataGridViewCheckBoxCell)
                'AuthAccessCheckBox.Value = accessDenied
                currentRow.Cells("RowAccessState").Value = RowAccessStates.AccessDenied
                currentRow.Cells("RowState").Value = RowDataStates.Hidden
                If (level > (CurrentlevelfromUI + MaxShowDepth.Value)) Then
                    currentRow.Visible = False
                Else
                    currentRow.Visible = True
                    DataGridView1.Refresh()
                End If
                If (level <> 0) Then
                    currentRow.DefaultCellStyle.ForeColor = SubLevelActiveForeColor(level - 1)
                    currentRow.DefaultCellStyle.BackColor = SubLevelActiveBackColor(level - 1)
                Else
                    currentRow.DefaultCellStyle.ForeColor = DriveInActiveForeColor
                    currentRow.DefaultCellStyle.BackColor = DriveInActiveBackColor
                End If
            End If
        End Try


        If accessDenied Then
            level -= 1
            Cursor.Current = cursorStack.Pop()
            Return details
        End If

        If (Not currentRow Is Nothing) Then
            currentRow.Cells("TotalDirCount").Value = "Busy"
            currentRow.Cells("TotalFileCount").Value = "Busy"
        End If

        Try
            For Each ChildFile As System.IO.FileInfo In Files

                details.StorageSize += ChildFile.Length
            Next
            LocalChildCount = Dirs.Length
        Catch ex As Exception
            'Just ignore these errors. That data just won't be counted
            Dim i = 0
        End Try



        Try
            For Each ChildDirectory As System.IO.DirectoryInfo In Dirs
                ChildCount += 1
                Try
                    Dim detailsTemp = GetDirectoryInfo(DriveName, directoryInf.FullName, ChildDirectory, RowTag, ChildCount, ThisDirIndex, level)

                    details.Add(detailsTemp)

                    'Max finds to zero mean get all
                    If Not MaxFinds.Value = 0 Then
                        If ChildCount > (MaxFinds.Value - 1) Then Exit For
                    End If

                Catch ex As Exception
                    Dim i As Integer = 0
                    'Continue with other children if there is an error
                End Try
            Next
        Catch ex As Exception
            MessageBox.Show("Error: Loc 4.2 Level " + level.ToString() + " Directory " + Name, "FileSystemExplorer", MessageBoxButtons.OK, MessageBoxIcon.Error)
            'Possible access error
        End Try


        If (Not currentRow Is Nothing) Then
            currentRow.Cells("StorageSize").Value = details.StorageSize.ToString("N0", CultureInfo.InvariantCulture)
            currentRow.Cells("TotalDirCount").Value = details.DirsCount.ToString("N0", CultureInfo.InvariantCulture)
            currentRow.Cells("TotalFileCount").Value = details.FileCount.ToString("N0", CultureInfo.InvariantCulture)
            If (level > (MaxShowDepth.Value)) Then
                currentRow.Visible = False
            Else
                DataGridView1.Refresh()
            End If
            If (level <> 0) Then
                currentRow.DefaultCellStyle.ForeColor = SubLevelActiveForeColor(level - 1)
                currentRow.DefaultCellStyle.BackColor = SubLevelActiveBackColor(level - 1)
            Else
                currentRow.DefaultCellStyle.ForeColor = DriveInActiveForeColor
                currentRow.DefaultCellStyle.BackColor = DriveInActiveBackColor
            End If
        End If

        level -= 1

        Cursor.Current = cursorStack.Pop()
        Return details
    End Function

    Private Enum RowDataStates
        Uninitiated
        Visible
        Hidden
    End Enum
    Private Enum RowAccessStates
        OK
        AccessDenied
    End Enum

End Class
